package com.culture.bootdemo.utils;


import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.EnumUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class EnumUtil extends EnumUtils {

    public static <T> String getMessage(Class<T> enumT, Integer code) {
        return EnumUtil.EnumToMap(enumT).get(code);
    }

    public static <T> String getMessage(Class<T> enumT, String code) {
        return EnumUtil.EnumToMap(enumT).get(Integer.valueOf(code));
    }

    public static <T> String getMessage(Class<T> enumT, Integer code, String... methodNames) {
        return EnumUtil.EnumToMap(enumT, methodNames).get(code);
    }


    /**
     * 枚举转map结合value作为map的key,description作为map的value
     */
    public static <T> Map<Object, String> EnumToMap(Class<T> enumT, String... methodNames) {
        Map<Object, String> enummap = new HashMap<>(2);
        if (!enumT.isEnum()) {
            return enummap;
        }
        T[] enums = enumT.getEnumConstants();
        if (enums == null || enums.length <= 0) {
            return enummap;
        }
        int count = methodNames.length;
        String valueMethod = "getCode"; //默认接口value方法
        String desMethod = "getMsg";//默认接口description方法
        if (count >= 1 && !"".equals(methodNames[0])) { //扩展方法
            valueMethod = methodNames[0];
        }
        if (count == 2 && !"".equals(methodNames[1])) {
            desMethod = methodNames[1];
        }
        for (T tobj : enums) {
            try {
                Object resultValue = getMethodValue(valueMethod, tobj); //获取value值
                if ("".equals(resultValue)) {
                    continue;
                }
                Object resultDes = getMethodValue(desMethod, tobj); //获取description描述值
                if ("".equals(resultDes)) { //如果描述不存在获取属性值
                    resultDes = tobj;
                }
                enummap.put(resultValue, resultDes + "");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return enummap;
    }

    public static <T> T getEnumByCode(Class<T> enumT, Integer code) {
        return enumToMap(enumT).get(code);
    }

    private static <T> Map<Integer, T> enumToMap(Class<T> enumT) {
        if (!enumT.isEnum()) {
            return Collections.emptyMap();
        }
        T[] enums = enumT.getEnumConstants();
        Map<Integer, T> map = new HashMap<>(enums.length);
        for (T t : enums) {
            try {
                Field code = t.getClass().getDeclaredField("code");
                code.setAccessible(true);
                map.put((Integer) code.get(t), t);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return map;
    }

    /**
     * 枚举转map结合value作为map的key,description作为map的value
     *
     * @return
     */
    public static <T> List<JSONObject> enumToObject(Class<T> enumT, String... fieldsName) {
        if (!enumT.isEnum()) {
            return Collections.emptyList();
        }
        T[] enums = enumT.getEnumConstants();
        return enumToObject(Arrays.asList(enums), fieldsName);
    }

    public static <T> List<JSONObject> enumToObject(List<T> enums, String... fieldsName) {
        List<JSONObject> enumList = new ArrayList<>();
        if (enums == null || enums.size() <= 0) {
            return enumList;
        }
        if (fieldsName == null || fieldsName.length <= 0) {
            fieldsName = new String[]{"code", "msg", "statuses"};
        }
        Class<?> enumClass = enums.get(0).getClass();
        for (T t : enums) {
            JSONObject object = new JSONObject();
            for (String fieldName : fieldsName) {
                try {
                    Field field = enumClass.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    if (field.get(t) instanceof List) {
                        object.put("children", enumToObject((List) field.get(t)));
                    } else {
                        if ("code".equals(fieldName)) {
                            object.put("value", field.get(t));
                        } else {
                            object.put("label", field.get(t));
                        }
                    }
                } catch (NoSuchFieldException e) {
                    //不需要处理
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            enumList.add(object);
        }
        return enumList;
    }


    /**
     * 根据反射，通过方法名称获取方法值，忽略大小写的
     *
     * @param methodName
     * @param obj
     * @param args
     * @return return value
     */
    private static <T> Object getMethodValue(String methodName, T obj, Object... args) {
        Object resut = "";
        // boolean isHas = false;
        try {
            /********************************* start *****************************************/
            Method[] methods = obj.getClass().getMethods(); //获取方法数组，这里只要共有的方法
            if (methods.length <= 0) {
                return resut;
            }
            Method method = null;
            for (int i = 0, len = methods.length; i < len; i++) {
                if (methods[i].getName().equalsIgnoreCase(methodName)) { //忽略大小写取方法
                    // isHas = true;
                    methodName = methods[i].getName(); //如果存在，则取出正确的方法名称
                    method = methods[i];
                    break;
                }
            }
            if (method == null) {
                return resut;
            }
            resut = method.invoke(obj, args); //方法执行
            if (resut == null) {
                resut = "";
            }
            return resut; //返回结果
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resut;
    }

}
